package com.momoc.multi.chat.room.core.session;

import com.momoc.multi.chat.room.common.config.ClearRedisCache;
import com.momoc.multi.chat.room.common.proto.SystemMessage;
import com.momoc.multi.chat.room.common.utils.AssertUtil;
import com.momoc.multi.chat.room.common.utils.RedisUtils;
import com.momoc.multi.chat.room.common.vo.AppUserInfo;
import com.momoc.multi.chat.room.core.config.ErrorControllerAdvice;
import com.momoc.multi.chat.room.core.event.user.UserLoginEvent;
import com.momoc.netty.frame.config.SmartNettyProperties;
import com.momoc.netty.frame.event.annotation.WebsocketEvent;
import com.momoc.netty.frame.session.SessionManagerAbstract;
import com.momoc.netty.frame.session.vo.UserSessionInfo;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * aurora
 * 会话管理器
 * @author momoc
 * @version 1.0
 * @className SessionManagerContext
 * @description
 * @date 2023/7/5 18:17
 */
@WebsocketEvent
@RequiredArgsConstructor
public class SessionManagerContext extends SessionManagerAbstract<AppUserInfo> {


    private final ChannelManagerContext channelManagerContext;
    Logger log = LoggerFactory.getLogger(SessionManagerContext.class);

    final SmartNettyProperties smartNettyProperties;

    final RedisUtils redisUtils;
    final ClearRedisCache clearRedisCache;

    /**
     * 当前实例所有的会话channel
     *
     */
    public void connectAfter(Channel channel){
        ChannelId id = channel.id();
        String token = id.asShortText();
        SystemMessage.sessionBuildResponse_100.Builder builder = SystemMessage.sessionBuildResponse_100.newBuilder();
        builder.setToken(token);
        log.info("链接建立成功，分发token：{}", token);
        channel.writeAndFlush(builder.build());


    }

    @Override
    public void closeConnectAfter(UserSessionInfo<AppUserInfo> userSessionInfo) {
        AppUserInfo appUserInfo = userSessionInfo.getAppUserInfo();

        ChannelId id = userSessionInfo.getChannel().id();

        redisUtils.removeKey(String.valueOf(appUserInfo.getId()));

        log.info("用户下线：{}", appUserInfo.getId());

        clearRedisCache.clearOne(String.valueOf(appUserInfo.getId()));

        channelManagerContext.close(userSessionInfo);

    }

    @Override
    protected void beforeClearAllSessionIfo(Collection<UserSessionInfo<AppUserInfo>> values) {
//        //释放redis内存资源
//        for (UserSessionInfo<AppUserInfo> value : values) {
//            redisUtils.removeKey(String.valueOf(value.getAppUserInfo().getId()));
//        }
    }

    /**
     * 登录成功后，在会话session中放入对应的用户信息，根据实现的泛型
     * @param userLoginEvent
     */
    @Order(0)
    @EventListener(classes = UserLoginEvent.class )
    public void userLoginEventListener(UserLoginEvent userLoginEvent){
        String token = userLoginEvent.getAppUserInfo().getTokenWs();

        UserSessionInfo<AppUserInfo> userSessionInfo = this.getUserSessionInfo(token);
        log.info("加入回话登录中token：{}"  , token);
        userSessionInfo.setAppUserInfo(userLoginEvent.getAppUserInfo());
        AppUserInfo appUserInfo = userLoginEvent.getAppUserInfo();

        //在线状态丢入redis中
        redisUtils.hashSet(String.valueOf(appUserInfo.getId()), "machineId", smartNettyProperties.getMachineId());
        redisUtils.hashSet(String.valueOf(appUserInfo.getId()), "dataCenterId",smartNettyProperties.getDataCenterId());
        redisUtils.hashSet(String.valueOf(appUserInfo.getId()), "tokenWs", token);
        clearRedisCache.addClearSet(String.valueOf(appUserInfo.getId()));
        log.info("用户上线：{}", appUserInfo.getId());
    }

    public String isUserOnline(Long userid){
        String tokenWs = redisUtils.hashGet(String.valueOf(userid), "tokenWs");

        /**
         * 用户不在线不需要发送
         */
          return  AssertUtil.isEmpty(tokenWs) ? null : tokenWs;

    }

}
